package com.example.mtblog.tool;




import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.example.mtblog.common.Result;
import com.example.mtblog.dto.LoginUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import java.text.SimpleDateFormat;
import java.util.*;


@Slf4j
public class TokenUtils {
    private static final String SECRET = "qwertyuioplkjhgfdsazxcvbnmabcdefghijklmn";
    // redis key过期时间
    private static final Integer EXPIRE_TIME_IN_S = 12 * 60 * 60 ; //过期时间(12小时)

    public static final String BEARER = "Bearer ";

    //设置加密算法
    private static final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
    /**
     * 获取转换后的私钥对象
     * @return
     */
    public static SecretKey getSecretKey(){
        return Keys.hmacShaKeyFor(SECRET.getBytes());
    }



    /**
     * 创建令牌
     *
     * @param loginUser 登录用户信息
     * @return 令牌
     */
    public static String createToken(LoginUser loginUser) {


        String UUID = IdUtil.fastSimpleUUID();
        loginUser.setUUID(UUID);
        refreshToken(loginUser);  // 缓存用户信息到redis，key是tokenUUID



        Map<String,Object> payLoad = new HashMap<>();
        payLoad.put("name",UUID);

        return Jwts.builder()
                .setClaims(payLoad)
                .signWith(getSecretKey(),signatureAlgorithm)
                .compact();  // 创建token令牌
    }

    /**
     * 根据HttpServletRequest 获取用户信息
     *
     * @param request http请求对象
     * @return 用户信息
     */
    public static LoginUser getLoginUser(HttpServletRequest request, HttpServletResponse response) {

        //拿到Token
        String token =  request.getHeader("token");
        String tokenKey = "";
        if(token == null) return null;



        try {
            if (!token.trim().isEmpty() && token.startsWith(BEARER))
                token = token.replace(BEARER, "");

            //解析Token 拿到Redis的Key值
             tokenKey = (String) Objects.requireNonNull(parseToken(token)).get("name");

        }catch (Exception e){
            return null;
        }



        if(tokenKey == null)
            return null;

        return RedisUtils.getCacheObject("loginToken:"+tokenKey);

    }



    // 解析token 携带的信息
    public static Claims parseToken(String token) {

        try {
            return Jwts.parserBuilder()
                    .setSigningKey(getSecretKey())
                    .build()
                    .parseClaimsJws(token)
                    .getBody();

        } catch (Exception e) {
            log.warn("parseToken error! in TokenUtils");
            return null;
        }
    }



    /**
     * 刷新令牌有效期
     *
     * @param loginUser 登录信息
     */
    public static void refreshToken(LoginUser loginUser) {

        Date date = new Date();
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        loginUser.setLoginTime(dateFormat.format(date));
        long expireTime = date.getTime() + EXPIRE_TIME_IN_S * 1000;
        loginUser.setExpireTime(dateFormat.format(expireTime));

        //防止用户多设备登录同一账号
        String oldKey = "oldLoginToken:" + loginUser.getUser().getUid();

        if(RedisUtils.getCacheObject(oldKey)!=null)
            RedisUtils.deleteObject(RedisUtils.getCacheObject(oldKey));

        // 设置redis里的userKey
        String userKey = "loginToken:"+loginUser.getUUID();

        //缓存到redis里面
        RedisUtils.setCacheObject(userKey, loginUser, EXPIRE_TIME_IN_S);
        RedisUtils.setCacheObject(oldKey, userKey);


    }





}
